/*
 * 项目名称:    wms-server-jeecg
 * 创建人员:    gongwenkai
 * 创建时间:    2023-09-26
 */
package org.jeecg.modules.flow.callback.delivery.task;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import lombok.RequiredArgsConstructor;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.exception.JeecgBootException;
import org.jeecg.common.util.FillRuleUtil;
import org.jeecg.modules.business.delivery.entity.WmsDeliveryTask;
import org.jeecg.modules.business.delivery.entity.WmsDeliveryTaskMaterial;
import org.jeecg.modules.business.delivery.entity.vo.WmsDeliveryTaskVO;
import org.jeecg.modules.business.delivery.service.IWmsDeliveryTaskMaterialService;
import org.jeecg.modules.business.delivery.service.IWmsDeliveryTaskService;
import org.jeecg.modules.business.doc.business.entity.WmsInReceiptMaterial;
import org.jeecg.modules.business.doc.business.vo.WmsInReceiptPage;
import org.jeecg.modules.business.outbound.entity.WmsOutReceiptTask;
import org.jeecg.modules.business.outbound.entity.WmsOutReceiptTaskMaterial;
import org.jeecg.modules.business.outbound.entity.vo.OutBoundTaskSaveVO;
import org.jeecg.modules.business.outbound.service.IWmsOutReceiptTaskService;
import org.jeecg.modules.business.warehouse.entity.WmsInReceiptTaskMaterial;
import org.jeecg.modules.business.warehouse.entity.vo.WmsInReceiptTaskPage;
import org.jeecg.modules.flow.callback.enums.DocumentStatusEnum;
import org.jeecg.modules.flow.callback.outbound.util.CommonOutboundUtil;
import org.jeecg.modules.flow.record.entity.WmsFlowRecord;
import org.jeecg.modules.flow.sys.common.BaseCustomBeanRun;
import org.jeecg.modules.flow.sys.entity.dto.BaseFlowDto;
import org.jeecg.modules.flow.sys.entity.dto.WorkFlowInfoDto;
import org.jeecg.modules.flow.sys.service.WorkFlowService;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;

/**
 * 调拨任务提交 回调Bean
 *
 * @author gongwenkai
 * @version 1.0.0
 * @since 2023-09-26
 */
@RequiredArgsConstructor
@Component
public class DeliveryTaskSubmitBean<T> extends BaseCustomBeanRun<T> {


    private final IWmsDeliveryTaskService deliveryTaskService;

    private final IWmsDeliveryTaskMaterialService deliveryTaskMaterialService;
    private final WorkFlowService workFlowService;

    /**
     * 业务逻辑 调拨任务提交
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void actureRun() {
        BaseFlowDto baseFlowDto = this.getBaseFlowDto();
        // 获取请求参数
        baseFlowDto.translateClass(WmsDeliveryTaskVO.class);
        WmsDeliveryTaskVO wmsDeliveryTaskVO = (WmsDeliveryTaskVO) baseFlowDto.getData();
        String taskId = wmsDeliveryTaskVO.getId();
        if (StrUtil.isEmpty(taskId)) {
            //直接提交
            WmsDeliveryTask wmsDeliveryTask = BeanUtil.toBean(wmsDeliveryTaskVO, WmsDeliveryTask.class);
            taskId = deliveryTaskService.saveMain(wmsDeliveryTask, wmsDeliveryTaskVO.getWmsDeliveryTaskMaterialList());
        } else {
            WmsDeliveryTask dbWmsDeliveryTask = deliveryTaskService.getById(taskId);
            if (Objects.isNull(dbWmsDeliveryTask)) {
                throw new JeecgBootException("调拨任务不存在");
            }
            if (DocumentStatusEnum.CLOSE.getCode().equals(dbWmsDeliveryTask.getDocumentStatus())) {
                throw new JeecgBootException("提交失败，所属调拨任务已关闭");
            }

            BeanUtil.copyProperties(dbWmsDeliveryTask,wmsDeliveryTaskVO);
            List<WmsDeliveryTaskMaterial> deliveryTaskMaterialList = deliveryTaskMaterialService.list(new LambdaQueryWrapper<WmsDeliveryTaskMaterial>()
                    .eq(WmsDeliveryTaskMaterial::getWmsDeliveryTaskId, taskId)
            );
            wmsDeliveryTaskVO.setWmsDeliveryTaskMaterialList(deliveryTaskMaterialList);
        }
        //自动创建出库任务 入库任务
        String outTaskCode=createOutTask(wmsDeliveryTaskVO);
        String inTaskCode=createInTask(wmsDeliveryTaskVO);
        deliveryTaskService.update(new LambdaUpdateWrapper<WmsDeliveryTask>()
                .set(WmsDeliveryTask::getDocumentStatus, DocumentStatusEnum.COMMIT.getCode())
                .set(WmsDeliveryTask::getInTaskCode,inTaskCode)
                .set(WmsDeliveryTask::getOutTaskCode,outTaskCode)
                .eq(WmsDeliveryTask::getId,taskId));
        // 当前前端调用业务需要你返回的
        baseFlowDto.setResult(Result.OK());
        // id是保存业务记录的id。用于生成业务流程信息记录
        baseFlowDto.setInfoId(taskId);
    }

    /**
     * 创建出库调拨任务
     */
    private String createOutTask(WmsDeliveryTaskVO deliveryTaskVO){

        OutBoundTaskSaveVO saveVo=new OutBoundTaskSaveVO();
        // 处理出库任务需要的字段
        saveVo.setOrganization(deliveryTaskVO.getOrganization());
        if("DB1".equals(deliveryTaskVO.getDocumentType())){
            saveVo.setDocumentType("C102");
        }else if("DB2".equals(deliveryTaskVO.getDocumentType())){
            saveVo.setDocumentType("C104");
        }
        saveVo.setDocumentCode((String) FillRuleUtil.executeRule("ckrw_rule", null));
        saveVo.setOwnerType("1");
        saveVo.setTaskDate(new Date());
        saveVo.setSysOrgCode(deliveryTaskVO.getSysOrgCode());
        saveVo.setOwner(deliveryTaskVO.getOwner());
        saveVo.setWarehouseKeeper("默认");
        saveVo.setDocumentStatus(DocumentStatusEnum.SAVE.getCode());
        saveVo.setOriginalSystem(deliveryTaskVO.getOriginalSystem());
        //设置调拨任务单号
        saveVo.setTransferApplicationOrder(deliveryTaskVO.getDocumentCode());
        //设置在途归属
        saveVo.setInTransitOwnership(deliveryTaskVO.getInTransitOwnership());
        List<WmsDeliveryTaskMaterial> deliveryTaskMaterialList = deliveryTaskVO.getWmsDeliveryTaskMaterialList();
        List<WmsOutReceiptTaskMaterial> outReceiptTaskMaterialList=new ArrayList<>();
        if(!CollectionUtil.isEmpty(deliveryTaskMaterialList)){
            for(WmsDeliveryTaskMaterial deliveryTaskMaterial:deliveryTaskMaterialList){
                //处理物料明细
                WmsOutReceiptTaskMaterial outReceiptTaskMaterial=new WmsOutReceiptTaskMaterial();
                BeanUtil.copyProperties(deliveryTaskMaterial,outReceiptTaskMaterial);
                outReceiptTaskMaterial.setId(null);
                //额外处理其他字段
                outReceiptTaskMaterial.setWmsBasicWarehouseId(deliveryTaskMaterial.getOutWarehouseId());
                outReceiptTaskMaterial.setWmsBasicWarehouseAreaId(deliveryTaskMaterial.getOutWarehouseAreaId());
                outReceiptTaskMaterial.setWmsBasicWarehouseAreaLocationId(deliveryTaskMaterial.getInWarehouseAreaLocationId());
                outReceiptTaskMaterial.setPlanQuantity(deliveryTaskMaterial.getDeliveryQuantity());
                outReceiptTaskMaterial.setHasOutboundQuantity(BigDecimal.ZERO);
                //设置调拨单号
                outReceiptTaskMaterial.setTransferApplicationOrder(deliveryTaskVO.getDocumentCode());
                outReceiptTaskMaterialList.add(outReceiptTaskMaterial);
            }
        }
        saveVo.setWmsOutReceiptTaskMaterialList(outReceiptTaskMaterialList);
        saveVo.setId(null);
        BaseFlowDto outTaskCommitFlowDto = getOutTaskCommitFlowDto(saveVo.getDocumentType());
        outTaskCommitFlowDto.setData(saveVo);
        workFlowService.commit(outTaskCommitFlowDto);
        return saveVo.getDocumentCode();
    }

    /**
     * 创建入库调拨任务
     */
    private String createInTask(WmsDeliveryTaskVO deliveryTaskVO){
        WmsInReceiptTaskPage saveVo =new WmsInReceiptTaskPage();
        // 处理出库任务需要的字段
        saveVo.setOrganization(deliveryTaskVO.getOrganization());
        if("DB1".equals(deliveryTaskVO.getDocumentType())){
            saveVo.setDocumentType("R101");
        }else if("DB2".equals(deliveryTaskVO.getDocumentType())){
            saveVo.setDocumentType("R105");
        }
        saveVo.setDocumentCode((String) FillRuleUtil.executeRule("rkrw_rule", null));
        saveVo.setOwnerType("1");
        saveVo.setSysOrgCode(deliveryTaskVO.getSysOrgCode());
        saveVo.setOwner(deliveryTaskVO.getOwner());
        saveVo.setWarehouseKeeper("默认");
        saveVo.setDocumentStatus(DocumentStatusEnum.SAVE.getCode());
        saveVo.setTaskDate(new Date());
        saveVo.setOriginalSystem(deliveryTaskVO.getOriginalSystem());
        //设置调拨任务单号
        saveVo.setTransferApplicationOrder(deliveryTaskVO.getDocumentCode());
        List<WmsDeliveryTaskMaterial> deliveryTaskMaterialList = deliveryTaskVO.getWmsDeliveryTaskMaterialList();
        List<WmsInReceiptTaskMaterial> inReceiptTaskMaterialList=new ArrayList<>();
        if(!CollectionUtil.isEmpty(deliveryTaskMaterialList)){
            for(WmsDeliveryTaskMaterial deliveryTaskMaterial:deliveryTaskMaterialList){
                //处理物料明细
                WmsInReceiptTaskMaterial inReceiptTaskMaterial=new WmsInReceiptTaskMaterial();
                BeanUtil.copyProperties(deliveryTaskMaterial,inReceiptTaskMaterial);
                inReceiptTaskMaterial.setId(null);
                //额外处理其他字段
                inReceiptTaskMaterial.setWmsBasicWarehouseId(deliveryTaskMaterial.getInWarehouseId());
                inReceiptTaskMaterial.setWmsBasicWarehouseAreaId(deliveryTaskMaterial.getInWarehouseAreaId());
                inReceiptTaskMaterial.setWmsBasicWarehouseAreaLocationId(deliveryTaskMaterial.getInWarehouseAreaLocationId());
                inReceiptTaskMaterial.setPlanQuantity(deliveryTaskMaterial.getDeliveryQuantity());
                //设置调拨单号
                inReceiptTaskMaterial.setTransferApplicationOrder(deliveryTaskVO.getDocumentCode());
                inReceiptTaskMaterialList.add(inReceiptTaskMaterial);
            }
        }
        saveVo.setWmsInReceiptTaskMaterialList(inReceiptTaskMaterialList);
        saveVo.setId(null);
        BaseFlowDto inTaskCommitFlowDto = getInTaskCommitFlowDto(saveVo.getDocumentType());
        inTaskCommitFlowDto.setData(saveVo);
        workFlowService.commit(inTaskCommitFlowDto);
        return saveVo.getDocumentCode();
    }

    /**
     * 获取调拨出库任务的提交节点信息
     * @return
     */
    private BaseFlowDto getOutTaskCommitFlowDto(String documentType){
        //查询调拨出库任务流程节点信息
        WorkFlowInfoDto workFlowInfoDto = new WorkFlowInfoDto();
        workFlowInfoDto.setBusinessType("outbound_task");
        workFlowInfoDto.setDocumentType(documentType);
        List<WmsFlowRecord> wmsFlowRecordList = workFlowService.workFlowInfo(workFlowInfoDto);
        if(CollectionUtil.isEmpty(wmsFlowRecordList)){
            throw new JeecgBootException("查询不到调拨出库任务流程，无法创建调拨出库任务");
        }
        WmsFlowRecord commitFlowRecord = CollectionUtil.get(wmsFlowRecordList,1);
        if(Objects.isNull(commitFlowRecord)){
            throw new JeecgBootException("查询不到调拨出库任务流程，无法创建调拨出库任务");
        }
        BaseFlowDto commitFlowDto = new BaseFlowDto();
        commitFlowDto.setCode(commitFlowRecord.getFlowCode());
        commitFlowDto.setBusinessType("outbound_task");
        commitFlowDto.setDocumentType(documentType);
        return commitFlowDto;
    }
    /**
     * 获取调拨入库任务的提交节点信息
     * @return
     */
    private BaseFlowDto getInTaskCommitFlowDto(String documentType){
        //查询调拨入库任务流程节点信息
        WorkFlowInfoDto workFlowInfoDto = new WorkFlowInfoDto();
        workFlowInfoDto.setBusinessType("document_task");
        workFlowInfoDto.setDocumentType(documentType);
        List<WmsFlowRecord> wmsFlowRecordList = workFlowService.workFlowInfo(workFlowInfoDto);
        if(CollectionUtil.isEmpty(wmsFlowRecordList)){
            throw new JeecgBootException("查询不到调拨入库任务流程，无法创建调拨入库任务");
        }
        WmsFlowRecord commitFlowRecord = CollectionUtil.get(wmsFlowRecordList,1);
        if(Objects.isNull(commitFlowRecord)){
            throw new JeecgBootException("查询不到调拨出库任务流程，无法创建调拨出库任务");
        }
        BaseFlowDto commitFlowDto = new BaseFlowDto();
        commitFlowDto.setCode(commitFlowRecord.getFlowCode());
        commitFlowDto.setBusinessType("document_task");
        commitFlowDto.setDocumentType(documentType);
        return commitFlowDto;
    }
}
